// 知识点1：对象生命周期：全局对象在程序启动时分配，在程序结束时销毁。局部自动对象，当我们进入其定义所在程序块时被创建，在离开块时被销毁。局部static对象在第一次使用前分配，在程序结束时销毁

// 知识点2：除了static和自动对象外，C++还支持动态对象的分配。动态分配的对象的生存期与它们在哪里创建无关，只有被显示的释放时，这些对象才会被销毁

// 知识点3：动态对象的释放是编程中极其容易出问题的地方，为了安全使用动态对象，标准库定义了两个智能指针类型来管理动态分配对象，当一个对象应该被释放时，指向它的智能指针可以确保自动释放它

// 知识点4：静态内存：保存局部static对象、类static对象、定义在任何函数之外的对象，由编译器自动创建和销毁。栈内存：保存定义在函数之内的非static对象，栈对象仅在定义的程序块运行时才存在

// 知识点5：除了静态内存和栈内存，每个程序还拥有一个内存池，这部分内存被称为自由空间或堆，程序用堆来存储动态分配的对象：在程序运行时分配的对象，其生存周期由程序来控制，也就是说，当动态对象不再使用时，我们必须显式的销毁：必须正确的管理动态内存

// 知识点6：C++中动态内存的管理是通过一对运算符来完成的，new：在动态内存中为对象分配空间并返回一个指向该对象的指针。delete：接受一个动态对象的指针，销毁该对象，并释放与之关联的内存

// 知识点7：忘记释放内存：内存泄漏，在尚有指针引用内存的情况下释放了内存，就会产生引用非法内存的指针

// 知识点8：为了更安全的使用动态内存，新标准库定义了两种智能指针类型来管理动态对象，头文件为memory，智能指针的主要作用就是自动释放所指向的对象，shared_ptr类型允许多个指针指向同一对象，unique_ptr类型则独占所指向对象

// 知识点9：智能指针类似与vector，用法上有相同的地方，下面是shared_ptr的定义方式

// shared_ptr<string> p1;//定义一个智能指针，指向对象为string类型
// shared_ptr<list<int>> p2;

// vector<string> p1;//智能指针也是模版
// vector<list<int>> p2;

// 知识点10：智能指针的使用方式与内置类型指针相似，解引用也是返回所指向对象，若在条件判断中使用，检测其是否为空

// 知识点11：make_shared()函数：最安全的分配和使用动态内存的方法，此函数在动态内存中分配一个对象并初始化它，返回指向该对象的shared_ptr，头文件为memory

// shared_ptr<int> p3 =
// make_shared<int>(42);//p3为智能指针，指向一个值为42的对象 auto p3 =
// make_shared<int>(42);//利用auto比较简便，若不传递任何参数，会值初始化

// 知识点12：每个shared_ptr都有一个关联的计数器，称为引用计数，个人理解就是该对象被引用的次数，拷贝情况下会递增：

// 1：用一个shared_ptr初始化另一个shared_ptr(拷贝)

// 2：将一个shared_ptr传递给一个函数当参数，值传递(拷贝)

// 3：作为函数的返回值，(返回的是自身的拷贝，也就是活引用的次数+1)

// 计数器递减情况：

// 1：给shared_ptr赋予一个新值(也就是说自身指向了另外一个地址，原来指向的对象已经没有引用者，则会自动释放)

// 2：一个shared_ptr离开其作用域时，会被销毁(递减)

// 当一个shared_ptr的计数器变为0，他就会自动释放自己所管理的对象，前提是其指向的对象只有一个引用者。

// 知识点13：当指向一个对象的最后一个shared_ptr被销毁时，该对象会被自动销毁：利用析构函数，会递减该对象的引用计数，当引用次数变为0，会销毁该对象

// 知识点14：相关联内存是否销毁：所有指向该内存的shared_ptr对象都被销毁，也就是计数器为0

// 知识点15：使用动态内存的原因：让多个对象共享相同的底层数据。也就是说拷贝的情况虽然发生，但是并不是元素的拷贝，而是将本身的指向拷贝给另一个指针对象，让这一个对象也指向自己所指向的对象，这样在本身释放以后，还有另一个对象指向自身原来所指向的对象。

// 由知识点15：b1和b2都包含4个元素。
